package instance

import (
	"cloud_android_backend/api/common"
	"cloud_android_backend/pkg/middleware/authorization"
	"cloud_android_backend/pkg/models/resources"
	model "cloud_android_backend/pkg/models/users"
	"cloud_android_backend/pkg/modules/instances"
	"cloud_android_backend/pkg/modules/orders"
	"cloud_android_backend/pkg/modules/realphone"
	"encoding/json"
	"github.com/gin-gonic/gin"
	"github.com/golang/glog"
	"modules.tenxcloud.com/common/composite"
	rb "modules.tenxcloud.com/common/middleware"
	"net/http"
	"strconv"
)

func Register(application *gin.RouterGroup) {
	application.POST("/containers/init", rb.RequestBody, InitContainers)
	application.POST("/containers/destroy_all", rb.RequestBody, DestroyAll)
	application.GET("/containers/list", authorization.TokenCheck, GetInstanceList)
	application.POST("/containers/renew", rb.RequestBody, authorization.TokenCheck, RenewInstance)
	application.POST("/containers/restart", rb.RequestBody, authorization.TokenCheck, RestartInstance)
	application.POST("/containers/info", rb.RequestBody, authorization.TokenCheck, GetInstanceInfo)
	application.GET("/realphone/list", authorization.TokenCheck, RealPhoneModelList)
	application.POST("/realphone/change_model", rb.RequestBody, authorization.TokenCheck, ChangePhoneModel)
	application.POST("/realphone/easy_recreate", rb.RequestBody, authorization.TokenCheck, EasyToRecreateNewInstance)
	application.POST("/realphone/batch_change_model", rb.RequestBody, authorization.TokenCheck, BatchChangePhoneModel)
	application.POST("/realphone/batch_easy_recreate", rb.RequestBody, authorization.TokenCheck, BatchEasyToRecreateNewInstance)
	application.POST("/containers/batch_restart", rb.RequestBody, authorization.TokenCheck, BatchRestartInstances)
	application.POST("/containers/batch_reset", rb.RequestBody, authorization.TokenCheck, BatchResetInstances)
	application.POST("/containers/transfer_text", rb.RequestBody, authorization.TokenCheck, TransferText)
	application.POST("/tools/switch_local_keyboard", rb.RequestBody, authorization.TokenCheck, SwitchLocalKeyboard)
	//application.GET("/", GetInstanceList)
}
func InitContainers(c *gin.Context) {
	body, _ := c.Get(rb.RequestBodyKey)
	initParam := instances.InitInstancesParam{}
	if err := json.Unmarshal(body.([]byte), &initParam); err != nil {
		glog.Error(err)
		c.AbortWithStatusJSON(common.ErrorResponse(err.Error()))
		return
	}
	if err := instances.InitInstances(initParam); err != nil {
		glog.Error(err)
		c.AbortWithStatusJSON(common.ErrorResponse(err.Error()))
		return
	}
	c.JSON(http.StatusOK, common.SuccessResponse("success"))
}

func DestroyAll(c *gin.Context) {
	body, _ := c.Get(rb.RequestBodyKey)
	destroyParam := instances.DestroyAllInstancesParam{}
	if err := json.Unmarshal(body.([]byte), &destroyParam); err != nil {
		glog.Error(err)
		c.AbortWithStatusJSON(common.ErrorResponse(err.Error()))
		return
	}
	if err := instances.DestroyAllInstances(destroyParam); err != nil {
		glog.Error(err)
		c.AbortWithStatusJSON(common.ErrorResponse(err.Error()))
		return
	}
	c.JSON(http.StatusOK, common.SuccessResponse("success"))
}

func GetInstanceList(c *gin.Context) {
	li, exists := c.Get(authorization.LoginUserKey)
	if !exists {
		c.AbortWithStatusJSON(common.ErrorResponse("get user from content failed"))
		return
	}
	current := li.(*model.User)
	db, err := composite.Database.GetOrm()
	if err != nil {
		glog.Error(err)
		c.AbortWithStatusJSON(common.ErrorResponse(err.Error()))
		return
	}
	instancesUsesModel := resources.InstanceUses{UserId: current.UserID}
	instancesUses, err := instancesUsesModel.GetListByUserId(db)
	if err != nil {
		glog.Error(err)
		c.AbortWithStatusJSON(common.ErrorResponse(err.Error()))
		return
	}
	c.JSON(http.StatusOK, common.SuccessResponse(instancesUses))
}

//	func RenewInstance(c *gin.Context) {
//		body, _ := c.Get(rb.RequestBodyKey)
//		renewParam := instances.RenewInstanceParam{}
//		if err := json.Unmarshal(body.([]byte), &renewParam); err != nil {
//			glog.Error(err)
//			c.AbortWithStatusJSON(common.ErrorResponse(err.Error()))
//			return
//		}
//		if err := instances.RenewInstance(renewParam); err != nil {
//			glog.Error(err)
//		}
//	}
func RenewInstance(c *gin.Context) {
	li, exists := c.Get(authorization.LoginUserKey)
	if !exists {
		c.AbortWithStatusJSON(common.ErrorResponse("get user from content failed"))
		return
	}
	current := li.(*model.User)
	body, _ := c.Get(rb.RequestBodyKey)
	renewParam := orders.RenewInstanceReq{}
	if err := json.Unmarshal(body.([]byte), &renewParam); err != nil {
		glog.Error(err)
		c.AbortWithStatusJSON(common.ErrorResponse(err.Error()))
		return
	}
	res, err := orders.RenewInstance(renewParam, current.UserID)
	if err != nil {
		glog.Error(err)
		c.AbortWithStatusJSON(common.ErrorResponse(err.Error()))
		return
	}
	c.JSON(http.StatusOK, common.SuccessResponse(res))
}

func RestartInstance(c *gin.Context) {
	li, exists := c.Get(authorization.LoginUserKey)
	if !exists {
		c.AbortWithStatusJSON(common.ErrorResponse("get user from content failed"))
		return
	}
	current := li.(*model.User)
	body, _ := c.Get(rb.RequestBodyKey)
	restartParam := instances.OpInstanceParams{}
	if err := json.Unmarshal(body.([]byte), &restartParam); err != nil {
		glog.Error(err)
		c.AbortWithStatusJSON(common.ErrorResponse(err.Error()))
		return
	}
	if err := instances.RestartInstance(restartParam, current.UserID); err != nil {
		glog.Error(err)
		c.AbortWithStatusJSON(common.ErrorResponse(err.Error()))
	}
	c.JSON(http.StatusOK, common.SuccessResponse("success"))
}

func GetInstanceInfo(c *gin.Context) {
	li, exists := c.Get(authorization.LoginUserKey)
	if !exists {
		c.AbortWithStatusJSON(common.ErrorResponse("get user from content failed"))
		return
	}
	current := li.(*model.User)
	body, _ := c.Get(rb.RequestBodyKey)
	param := instances.OpInstanceParams{}
	if err := json.Unmarshal(body.([]byte), &param); err != nil {
		glog.Error(err)
		c.AbortWithStatusJSON(common.ErrorResponse(err.Error()))
		return
	}
	instance, err := instances.GetInstanceInfo(param.InstanceUseId)
	if err != nil {
		glog.Error(err)
		c.AbortWithStatusJSON(common.ErrorResponse(err.Error()))
	}
	if instance.UserId != current.UserID {
		c.AbortWithStatusJSON(common.ErrorResponse("Permission denied"))
		return
	}
	c.JSON(http.StatusOK, common.SuccessResponse(instance))
	return
}

func RealPhoneModelList(c *gin.Context) {
	androidVersion := c.Query("android_version")
	if androidVersion == "" {
		androidVersion = "13"
	}
	androidVersionInt, err := strconv.Atoi(androidVersion)
	if err != nil {
		androidVersionInt = 13
	}
	list, err := realphone.GetRealPhoneListByAndroidVersion(androidVersionInt)
	if err != nil {
		glog.Error(err)
		c.AbortWithStatusJSON(common.ErrorResponse(err.Error()))
		return
	}
	c.JSON(http.StatusOK, common.SuccessResponse(list))
}

type ChangePhoneModelParam struct {
	InstanceUseId int64 `json:"instance_use_id"`
	ModelId       int64 `json:"model_id"`
}

func ChangePhoneModel(c *gin.Context) {
	li, exists := c.Get(authorization.LoginUserKey)
	if !exists {
		c.AbortWithStatusJSON(common.ErrorResponse("get user from content failed"))
		return
	}
	current := li.(*model.User)
	body, _ := c.Get(rb.RequestBodyKey)
	param := ChangePhoneModelParam{}
	if err := json.Unmarshal(body.([]byte), &param); err != nil {
		glog.Error(err)
		c.AbortWithStatusJSON(common.ErrorResponse(err.Error()))
		return
	}
	if err := realphone.ChangeRealPhoneModel(param.InstanceUseId, param.ModelId, current.UserID); err != nil {
		glog.Error(err)
		c.AbortWithStatusJSON(common.ErrorResponse(err.Error()))
		return
	}
	c.JSON(http.StatusOK, common.SuccessResponse("success"))

}

type EasyToRecreateNewInstanceParam struct {
	InstanceUseId int64 `json:"instance_use_id"`
}

func EasyToRecreateNewInstance(c *gin.Context) {

	li, exists := c.Get(authorization.LoginUserKey)
	if !exists {
		c.AbortWithStatusJSON(common.ErrorResponse("get user from content failed"))
		return
	}
	current := li.(*model.User)
	body, _ := c.Get(rb.RequestBodyKey)
	param := EasyToRecreateNewInstanceParam{}
	if err := json.Unmarshal(body.([]byte), &param); err != nil {
		glog.Error(err)
		c.AbortWithStatusJSON(common.ErrorResponse(err.Error()))
		return
	}
	if err := realphone.EasyToRecreateNewInstance(param.InstanceUseId, current.UserID); err != nil {
		glog.Error(err)
		c.AbortWithStatusJSON(common.ErrorResponse(err.Error()))
		return
	}
	c.JSON(http.StatusOK, common.SuccessResponse("success"))
}

type BatchChangePhoneModelParam struct {
	InstanceUseIds []int64 `json:"instance_use_ids"`
	ModelId        int64   `json:"model_id"`
}

func BatchChangePhoneModel(c *gin.Context) {
	li, exists := c.Get(authorization.LoginUserKey)
	if !exists {
		c.AbortWithStatusJSON(common.ErrorResponse("get user from content failed"))
		return
	}
	current := li.(*model.User)
	body, _ := c.Get(rb.RequestBodyKey)
	param := BatchChangePhoneModelParam{}
	if err := json.Unmarshal(body.([]byte), &param); err != nil {
		glog.Error(err)
		c.AbortWithStatusJSON(common.ErrorResponse(err.Error()))
		return
	}
	for _, instanceUseId := range param.InstanceUseIds {
		if err := realphone.ChangeRealPhoneModel(instanceUseId, param.ModelId, current.UserID); err != nil {
			glog.Error(err)
			c.AbortWithStatusJSON(common.ErrorResponse(err.Error()))
			return
		}
	}

	c.JSON(http.StatusOK, common.SuccessResponse("success"))
}

type BatchEasyToRecreateNewInstanceParam struct {
	InstanceUseIds []int64 `json:"instance_use_ids"`
}

func BatchEasyToRecreateNewInstance(c *gin.Context) {
	li, exists := c.Get(authorization.LoginUserKey)
	if !exists {
		c.AbortWithStatusJSON(common.ErrorResponse("get user from content failed"))
		return

	}
	current := li.(*model.User)
	body, _ := c.Get(rb.RequestBodyKey)
	param := BatchEasyToRecreateNewInstanceParam{}
	if err := json.Unmarshal(body.([]byte), &param); err != nil {
		glog.Error(err)
		c.AbortWithStatusJSON(common.ErrorResponse(err.Error()))
		return
	}
	for _, instanceUseId := range param.InstanceUseIds {
		if err := realphone.EasyToRecreateNewInstance(instanceUseId, current.UserID); err != nil {
			glog.Error(err)
			c.AbortWithStatusJSON(common.ErrorResponse(err.Error()))
			return
		}
	}
	c.JSON(http.StatusOK, common.SuccessResponse("success"))
}

type BatchRestartInstancesParam struct {
	InstanceUseIds []int64 `json:"instance_use_ids"`
}

func BatchRestartInstances(c *gin.Context) {
	li, exists := c.Get(authorization.LoginUserKey)
	if !exists {
		c.AbortWithStatusJSON(common.ErrorResponse("get user from content failed"))
		return
	}
	current := li.(*model.User)
	body, _ := c.Get(rb.RequestBodyKey)
	restartParam := BatchRestartInstancesParam{}
	if err := json.Unmarshal(body.([]byte), &restartParam); err != nil {
		glog.Error(err)
		c.AbortWithStatusJSON(common.ErrorResponse(err.Error()))
		return
	}
	for _, instanceUseId := range restartParam.InstanceUseIds {
		if err := instances.RestartInstance(instances.OpInstanceParams{InstanceUseId: instanceUseId}, current.UserID); err != nil {
			glog.Error(err)
			c.AbortWithStatusJSON(common.ErrorResponse(err.Error()))
			return
		}
	}

	c.JSON(http.StatusOK, common.SuccessResponse("success"))
}

func BatchResetInstances(c *gin.Context) {
	li, exists := c.Get(authorization.LoginUserKey)
	if !exists {
		c.AbortWithStatusJSON(common.ErrorResponse("get user from content failed"))
		return
	}
	current := li.(*model.User)
	body, _ := c.Get(rb.RequestBodyKey)
	resetParam := realphone.ResetPhoneDataParam{}
	if err := json.Unmarshal(body.([]byte), &resetParam); err != nil {
		glog.Error(err)
		c.AbortWithStatusJSON(common.ErrorResponse(err.Error()))
		return
	}
	for _, instanceUseId := range resetParam.InstanceUseId {
		if err := realphone.ResetPhoneData(instanceUseId, current.UserID); err != nil {
			glog.Error(err)
			c.AbortWithStatusJSON(common.ErrorResponse(err.Error()))
			return
		}
	}
	c.JSON(http.StatusOK, common.SuccessResponse("success"))
}
